/**
 * @brief Datagram, process udp's receiving and sending.
 * @details Datagram supports blocking io and nonblocking io.
 * @note Blocking io must use ReceiveN & SendN; nonblocking io must\n
 *       use Receive&Send.
 *
 * @author Huang RuiGuang
 * @date 2008/12/1
 *
 * Herm library
 * Copyright (c) 2008 by Huang RuiGuang(daemon.huang@gmail.com)
 *
 * Permission to use, copy, modify, distribute and sell this software.
 */

#ifndef HERM_SOCKET_BASIC_DATAGRAM_SOCKET
#define HERM_SOCKET_BASIC_DATAGRAM_SOCKET

#include "herm/base/socket/socket_base.h"

namespace herm{
class Address;

class HERM_API Datagram : public BasicSocket<Private::DatagramType>
{
public:
	/**
	 * @brief Create a udp socket object, attach a random port which is allocated by system.
	 * @exception Throw herm::Exception.
	 */
	Datagram();

	/**
	 * @brief Create a udp socket object, attach to \a addr.
	 * @param [addr] The address to be attached.
	 * @exception Throw herm::Exception.
	 */
	Datagram(const Address& addr);

	~Datagram(void);

	/**
	 * @brief Receive by blocking io. 
	 * @param [buffer] Receive buffer.
	 * @param [length] The size of \a buffer.
	 * @return 0, Server closes this socket handle.\n
	 *         >0, Receive bytes.
	 * @exception Occurred error, throw herm::Exception.
	 * 
	 */
	int Receive(char* buffer, int length);
	int Receive(char* buffer, int length, Address& addr);
	void Send(const char* buffer, int length, const Address& addr);

	/**
	 * @brief Receive by nonblocking io.
	 * @return 0, Server closes this socket handle.\n
	 *         >0, Receive bytes.
	 *         herm::COMPLETION, indicate the stack socket buffer is empty.
	 * @exception Occurred error, throw herm::Exception.
	 */
	int ReceiveNB(char* buffer, int length);
	int ReceiveNB(char* buffer, int length, Address& addr);

	/**
	 * @brief Sending by nonblocking io.
	 * @return >=0, Sent bytes.
	 *         herm::COMPLETION, indicate the stack socket buffer is full.
	 * @exception Occurred error, throw herm::Exception.
	 */
	int SendNB(const char* buffer, int length, const Address& addr);
};
}

#endif

